package cn.xinfei.xdecision.manager.controller.component.decisiontree;


import cn.xinfei.xdecision.common.model.common.PageResult;
import cn.xinfei.xdecision.common.model.common.ResponseEntityBuilder;
import cn.xinfei.xdecision.common.model.common.ResponseEntityDto;
import cn.xinfei.xdecision.common.model.common.requestParam.UpdateStatusParam;
import cn.xinfei.xdecision.common.model.component.CopyToFolderReqVo;
import cn.xinfei.xdecision.common.model.component.decisiontree.DecisionTree;
import cn.xinfei.xdecision.common.model.component.decisiontree.vo.DecisionTreeVo;
import cn.xinfei.xdecision.common.model.component.request.ListParam;
import cn.xinfei.xdecision.common.service.component.decisiontree.DecisionTreeService;
import cn.xinfei.xdecision.common.utils.constant.OperateNameConst;
import cn.xinfei.xdecision.common.utils.constant.OperateTypeEnum;
import cn.xinfei.xdecision.common.utils.constant.RedisConstant;
import cn.xinfei.xdecision.common.utils.enums.enginex.ComponentStatusEnum;
import cn.xinfei.xdecision.common.utils.exception.ApiException;
import cn.xinfei.xdecision.common.utils.exception.enums.ErrorCodeEnum;
import cn.xinfei.xdecision.manager.web.aop.ArchivesLog;
import com.baomidou.mybatisplus.extension.api.ApiController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.List;

@Api(tags = "组件中心-决策树")
@RestController
@RequestMapping("v3/decisionTree/")
@Slf4j
public class DecisionTreeController extends ApiController {

    @Resource
    private DecisionTreeService decisionTreeService;

    @Resource
    private RedissonClient redissonClient;

    @ApiOperation(value = "决策树_规则详情")
    @PostMapping(value = "getDecisionTreeInfo/{id}")
    public ResponseEntityDto<DecisionTreeVo> getDecisionTreeInfo(@PathVariable Long id) {
        if (id == null) {
            throw new ApiException(ErrorCodeEnum.PARAMS_EXCEPTION.getCode(), ErrorCodeEnum.PARAMS_EXCEPTION.getMessage());
        }
        return ResponseEntityDto.success(decisionTreeService.queryById(id));
    }

    @ApiOperation(value = "决策树_规则列表")
    @PostMapping(value = "getDecisionTreeList")
    public ResponseEntityDto<PageResult<List<DecisionTreeVo>, DecisionTree>> getDecisionTreeList(@RequestBody ListParam listParam) {
        return decisionTreeService.queryByEntity(listParam);
    }

    @ApiOperation(value = "决策树_规则启用")
    @PostMapping(value = "enableDecisionTree")
    @ArchivesLog(type = OperateTypeEnum.UPDATE, name = OperateNameConst.ComponentOpt.ENABLE)
    public ResponseEntityDto<String> enableDecisionTree(@RequestBody UpdateStatusParam param) {
        if (CollectionUtils.isEmpty(param.getList())) {
            throw new ApiException(ErrorCodeEnum.PARAMS_EXCEPTION.getCode(), "id集合必传");
        }
        decisionTreeService.updateDecisionTree(
                param.getList(),
                ComponentStatusEnum.ENABLE.getStatus(), "当前规则状态是" + ComponentStatusEnum.ENABLE.getName());
        return ResponseEntityDto.success("决策树规则启用成功!");
    }

    @ApiOperation(value = "决策树_规则停用")
    @PostMapping(value = "disableDecisionTree")
    @ArchivesLog(type = OperateTypeEnum.UPDATE, name = OperateNameConst.ComponentOpt.DISABLE)
    public ResponseEntityDto<String> disableDecisionTree(@RequestBody UpdateStatusParam param) {
        if (CollectionUtils.isEmpty(param.getList())) {
            throw new ApiException(ErrorCodeEnum.PARAMS_EXCEPTION.getCode(), "id集合必传");
        }
        decisionTreeService.updateDecisionTree(
                param.getList(),
                ComponentStatusEnum.DISABLE.getStatus(),
                "当前规则状态是" + ComponentStatusEnum.DISABLE.getName());
        return ResponseEntityDto.success("决策树规则停用成功!");
    }

    @ApiOperation(value = "决策树_保存规则及版本")
    @PostMapping(value = "saveDecisionTree")
    @ArchivesLog(type = OperateTypeEnum.CREATE, name = OperateNameConst.ComponentOpt.SAVE)
    public ResponseEntityDto<Long> checkAndSaveTree(@RequestBody DecisionTreeVo decisionTreeVo) {
        //获取分布式锁
        String key = MessageFormat.format(RedisConstant.RISK_ENGINE_BASIC_INFO_KEY,
                RedisConstant.COMPONENT_KEY,
                RedisConstant.DECISION_TREE,
                decisionTreeVo.getCode());
        RLock lock = redissonClient.getLock(key);
        if (!lock.tryLock()) {
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.RECEIPT_CONCURRENT_OPERATE_ERROR);
        }
        try {
            return ResponseEntityDto.success("保存决策树规则成功!", decisionTreeService.checkAndSaveTrees(decisionTreeVo));
        } catch (ApiException e) {
            log.error("保存决策树规则业务异常", e);
            return ResponseEntityBuilder.buildErrorResponse(e.getErrCode(), e.getMessage());
        } catch (Exception e) {
            log.error("保存决策树规则未知异常", e);
            return ResponseEntityBuilder.buildErrorResponse(ErrorCodeEnum.SERVER_ERROR);
        } finally {
            lock.unlock();
        }
    }

    @ApiOperation(value = "决策树_复制规则及全部版本")
    @PostMapping(value = "copyDecisionTrees")
    @ArchivesLog(type = OperateTypeEnum.CREATE, name = OperateNameConst.ComponentOpt.COPY)
    public ResponseEntityDto<DecisionTreeVo> copyDecisionTree(@RequestBody CopyToFolderReqVo req) {
        decisionTreeService.copyDecisionTree(req);
        return ResponseEntityDto.success("复制决策树成功!");
    }
}
